from sqlalchemy import exists, select, update
from sqlalchemy.ext.asyncio import AsyncSession
from sqlalchemy.orm import joinedload

from app.database.models import Order, Proxy, User


async def is_user_exists(session: AsyncSession, user_id: int) -> bool:

    q = select(exists().where(User.telegram_id == user_id))
    res = await session.execute(q)
    return res.scalar()


async def create_user(session: AsyncSession, user_id: int, username: str) -> None:

    user = User(telegram_id=user_id, username=username)
    session.add(user)
    await session.commit()


async def get_user(session: AsyncSession, user_id: int, joined: bool = False) -> User:

    q = select(User).where(User.telegram_id == user_id)

    if joined:
        q = q.options(
            joinedload(User.orders), joinedload(User.payments), joinedload(User.proxies)
        )

    res = await session.execute(q)

    return res.scalar()


async def get_users(session: AsyncSession, registered: bool = None) -> list[User]:

    q = select(User)
    if registered is not None:
        if registered:
            q = q.where(User.is_registered == 1)
        else:
            q = q.where(User.is_registered == 0)

    res = await session.execute(q)

    return res.scalars().all()


async def get_user_item(session: AsyncSession, item_id: int, user_id: int) -> Proxy:

    q = select(Order).where(Proxy.item_id == item_id).where(Proxy.user_id == user_id)
    res = await session.execute(q)

    return res.scalar()


async def get_user_language(session: AsyncSession, user_id: int) -> User:

    q = select(User.lang_code).where(User.telegram_id == user_id)
    res = await session.execute(q)

    return res.scalar()


async def change_user_language(
    session: AsyncSession, user_id: int, lang_code: str
) -> None:

    q = update(User).where(User.telegram_id == user_id).values(lang_code=lang_code)
    await session.execute(q)

    await session.commit()


async def reg_user(session: AsyncSession, user_id: int, email: str) -> None:
    q = (
        update(User)
        .where(User.telegram_id == user_id)
        .values(email=email, is_registered=1)
    )
    await session.execute(q)

    await session.commit()


async def increase_user_balance(
    session: AsyncSession, user_id: int, summ: float
) -> None:

    q = (
        update(User)
        .where(User.telegram_id == user_id)
        .values(balance=User.balance + summ)
    )

    await session.execute(q)

    await session.commit()
